#include <string.h>
#include <iostream>
#include <ostream>
using namespace std;
//using std::cout;
//using std::endl;

class String {
public:
    String() : _pstr(new char[1]()) {
        cout << "String()" << endl;
    }

    String(const char *pstr) : _pstr(new char[strlen(pstr) + 1]()) {
        cout << "String(const char *)" << endl;
        strcpy(_pstr, pstr);
    }

    /**
     * 移动构造
     * @param rhs
     */
    String(String &&rhs):_pstr(rhs._pstr) {
        rhs._pstr = nullptr;
        printf("move String()\n");
    }


    /**
     * 拷贝构造
     * @param rhs
     */
    String(const String &rhs) : _pstr(new char[strlen(rhs._pstr) + 1]()) {
        cout << "String(const String &)" << endl;
        strcpy(_pstr, rhs._pstr);
    }

    /**
     * 移动赋值函数
     * s1 = move(s1)需要判断自赋值
     * @param rhs
     * @return
     */
    String& operator=(String&& rhs){
        cout << "move String &operator=(const String &)" << endl;
//        右值引用本身是一个左值
        if(this != &rhs){
            delete[] _pstr;
            _pstr = rhs._pstr;
            rhs._pstr = nullptr;
        }
        return *this;
    }




    /**
     * 赋值运算符
     * @param rhs
     * @return
     */
    String &operator=(const String &rhs) {
        cout << "String &operator=(const String &)" << endl;
        if (this != &rhs) {
            if (_pstr) {
                delete[] _pstr;
            }
            _pstr = new char[strlen(rhs._pstr) + 1]();
            strcpy(_pstr, rhs._pstr);
        }
        return *this;
    }

    size_t length() const {
        size_t len = 0;
        if (_pstr) {
            len = strlen(_pstr);
        }
        return len;
    }

    const char *c_str() const {
        if (_pstr) {
            return _pstr;
        } else {
            return nullptr;
        }
    }

    ~String() {
        cout << "~String()" << endl;
        if (_pstr) {
            delete[] _pstr;
            _pstr = nullptr;
        }
    }

    void print() const {
        if (_pstr) {
            cout << "_pstr = " << _pstr << endl;
        } else {
            cout << endl;
        }
    }

private:
    char *_pstr;
};

ostream& operator<<(ostream& os, const String& rhs){
    os << rhs.c_str();
    return os;
}


void test0() {
//    String s1("hello");
//    拷贝构造
//    String s2 = s1;

    /**
     * 先构造，再拷贝构造
     * 利用"hello"这个字符串创建了一个临时对象并复制给了s3
     * 这一步实际上new了两次
     */
//    移动构造
    String s3 = "hello";
//    移动赋值
    s3 = String("world");

    s3 = s3;
    String("test") = String("test");

    cout << s3 << endl;
}

void test1() {
    int a = 1, b = 2;
    /**
     * const 才能绑定右值，拷贝构造的原理
     */
    const int &ref = (a + b);

    int &&ref2 = 12580;
}

void test2(){
    int a = 1;
    int &&ref = std::move(a);
    ref = 100;
    cout << a << endl;

    String s1("hello");
    /**
     * 会影响s1本体的内容,本质是把s1申请的堆空间管理权移交给s2
     */
    String s2 = move(s1);

    cout << s2 << endl;
    cout << s1 << endl;

    printf("%p\n", s1.c_str());
    printf("%p\n", s2.c_str());


}
void test3(){
    String s1("hello");
    s1 = move(s1);
}

/**
 * string对象在func2执行完就会销毁，此时不会调用拷贝构造，而是调用移动构造
 * @return
 */
String func2(){
    return String("wangdao");
}

String global("global var");
String func3(){
//    这里还是调用拷贝构造
    return global;
}

void test4(){
    /*func2().print();*/

//    发生了移动构造
    String&& ref = func2();
    cout << &ref << endl;
}


int main() {
    func3();
    return 0;
}